﻿
using Furion.DatabaseAccessor;
using Furion.DataEncryption;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.Core;
using Furion.Core.Entities.Enums;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Furion.DatabaseAccessor.Extensions;
using Microsoft.Extensions.Caching.Memory;
using System.Linq.Dynamic.Core;
using Furion.Application.Weixin;

namespace Furion.Application
{


    [AppAuthorize, ApiDescriptionSettings("System", Name = "User", Order = 1, Tag = "用户")]
    public class UserService : IDynamicApiController, IUserService, ITransient
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IRepository<User> _userRepository;

        private readonly IRepository<UserRole> _userRoleRepository;

        private readonly IAuthorizationManager _authorizationManager;


        /// <summary>
        /// 缓存
        /// </summary>
        private readonly IMemoryCache _memoryCache;

        public UserService(IHttpContextAccessor httpContextAccessor
            , IRepository<User> userRepository
            , IRepository<UserRole> userRoleRepository
            , IAuthorizationManager authorizationManager
            , IMemoryCache memoryCache
            )
        {
            _httpContextAccessor = httpContextAccessor;
            _userRepository = userRepository;
            _userRoleRepository = userRoleRepository;
            _authorizationManager = authorizationManager;
            _memoryCache = memoryCache;
        }


        /// <summary>
        /// 获取当前用户信息 [AllowAnonymous]
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous, HttpGet("/User/CurrentUserProfile"), ApiDescriptionSettings(Name = "CurrentUserProfile")]
        public UserProfile CurrentUserProfile()
        {
            if(_authorizationManager.IsAuthenticated)
            {
                var userId = _authorizationManager.UserId;
                var user_info = _userRepository.Include(a => a.Roles).FirstOrDefault(a => a.Id == userId).Adapt<UserProfile>();
                return user_info;
            }
            else
            {
                throw Oops.Oh("请重新登录");
            }
            

        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.USER_Profile), HttpGet("/User/UserProfile"), ApiDescriptionSettings(Name = "UserProfile")]
        public async Task<UserProfile> UserProfileAsync([Required,FromQuery] long userId)
        {
            // 查询用户是否存在
            var user = await _userRepository.Include(a => a.Roles).FirstOrDefaultAsync(u => u.Id == userId&& u.IsDeleted==false);
            return user.Adapt<UserProfile>();
        }


        /// <summary>
        /// 获取所有用户列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.USER_List), HttpGet("/User/PageList"), ApiDescriptionSettings(Name = "PageList")]
        public async Task<PagedList<UserProfile>> PageListAsync([FromQuery, Required] UserPageListInput input)
        {
            var hasKeyword = !string.IsNullOrEmpty(input.Keyword?.Trim());

            string orderBy = "asc";
            if (input.orderDirection == "asc")
            {
                orderBy = " asc ";
            }
            else
            {
                orderBy = " desc ";
            }
            string orderEx = " Id desc ";
            if (!string.IsNullOrEmpty(input.orderField))
            {
                orderEx = input.orderField + orderBy;
            }

            var users = await _userRepository.Include(a => a.Roles)
                .Where(a => a.IsDeleted == input.IsDeleted)
                .Where(hasKeyword, a => a.UserName.Contains(input.Keyword.Trim()) || a.NickName.Contains(input.Keyword.Trim()) || a.Remark.Contains(input.Keyword.Trim()))
                .OrderBy(orderEx)                 
                .ToPagedListAsync(input.PageIndex, input.PageSize);
            return users.Adapt<PagedList<UserProfile>>();
        }





        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.USER_Delete), HttpPost("/User/Delete"), ApiDescriptionSettings(Name = "Delete")]
        public async Task DeleteAsync([Required] UserDeleteInput input)
        {
            // 判断用户Id中是否有重复项
            var isRepeat = input.userIds.GroupBy(i => i).Any(g => g.Count() > 1);
            if (isRepeat) throw Oops.Oh(ErrorCodes.u1011);

            // 禁止删除自己
            if (input.userIds.Contains(_authorizationManager.UserId)) throw Oops.Oh(ErrorCodes.u1001);

            // 查询所有存在且不被引用的用户
            var users = await _userRepository.Include(u => u.Roles).Where(u => input.userIds.Contains(u.Id) ).ToListAsync(); //&& !u.Roles.Any()

            // 判断要操作的数据长度是是否等于传入数据的长度
            //if (input.userIds.Length != users.Count) throw Oops.Oh(ErrorCodes.u1007);

            var nowTime = DateTime.Now;
            users.ForEach(u =>
            {
                u.UpdatedTime = nowTime;
                u.IsDeleted = true;
            });
        }

        /// <summary>
        /// 恢复用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.USER_Delete), HttpPost("/User/Recovery"), ApiDescriptionSettings(Name = "Recovery")]
        public async Task RecoveryAsync([Required] UserDeleteInput input)
        {
            // 查询所有存在且不被引用的用户
            var users = await _userRepository.Where(u => input.userIds.Contains(u.Id)).ToListAsync();
            
            var nowTime = DateTime.Now;
            users.ForEach(u =>
            {
                u.UpdatedTime = nowTime;
                u.IsDeleted = false;
            });
        }



        /// <summary>
        /// 添加账号
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.USER_Add), HttpPost("/User/Add"), ApiDescriptionSettings(Name = "Add")]
        public async Task<long> AddAsync(UserAddInput input)
        {
            // 如果不需要返回自增Id，使用 InsertAsync即可
            var isExist = await _userRepository.AnyAsync(u => u.UserName.ToLower() == input.UserName.Trim().ToLower());
            if (isExist)
            {
                throw Oops.Oh("账号已经存在，添加失败");
            }
            else
            {
                var user = input.Adapt<User>();
                user.UserPass = MD5Encryption.Encrypt(input.UserPass.Trim());
                user.CreatedTime = DateTime.Now;
                user.UpdatedTime = DateTime.Now;
                user.CreatedUserId = _authorizationManager.UserId;
                user.OpenId = "";

                var newEntity = await _userRepository.InsertNowAsync(user);
                if (input.RoleIds.Length > 0)
                {
                    List<UserRole> list = new List<UserRole>();
                    foreach (int Id in input.RoleIds)
                    {
                        if(Id>0)
                        {
                            list.Add(new UserRole { RoleId = Id, UserId = newEntity.Entity.Id });
                        }                        
                    }
                    if(list.Count>0)
                    {
                        await _userRoleRepository.InsertNowAsync(list);
                    }
                    
                }

                return newEntity.Entity.Id;
            }            
        }



        /// <summary>
        /// 修改当前用户信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.USER_Edit),   HttpPost("/User/Edit"), ApiDescriptionSettings(Name = "Edit")]
        public async Task EditAsync(UserEditInput input)
        {
            var modle = await _userRepository.FirstOrDefaultAsync(a => a.Id == input.Id);
            if (modle != null)
            {                
                if (input.UserPass!= modle.UserPass)
                {
                    modle.UserPass = MD5Encryption.Encrypt(input.UserPass.Trim());
                }
                modle.UserName = input.UserName;
                modle.NickName = input.NickName;
                modle.ImageUrl = input.ImageUrl;
                modle.Remark = input.Remark;
                modle.Enabled = input.Enabled;
                modle.OrgId = input.OrgId;
                modle.Remark = input.Remark;
                modle.Mobile=input.Mobile;
                await _userRepository.UpdateNowAsync(modle);
                
                if (input.RoleIds.Length > 0)
                {
                    var items = await _userRoleRepository.DetachedEntities.Where(a => a.UserId == input.Id).ToListAsync();
                    if(items.Any())
                    {
                       await  _userRoleRepository.DeleteNowAsync(items);
                    }
                    
                    List<UserRole> list = new List<UserRole>();
                    foreach (int Id in input.RoleIds)
                    {
                        if(Id>0)
                        {
                            list.Add(new UserRole { RoleId = Id, UserId = input.Id });
                        }
                    }
                    if(list.Count>0)
                    {
                        await _userRoleRepository.InsertNowAsync(list);
                    }
                }                
            }
            else
            {
                throw Oops.Oh("账号不存在，操作错误");
            }

        }


        /// <summary>
        /// 修改当前用户密码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.USER_ChangePassword), HttpPost("/User/ChangePassword"), ApiDescriptionSettings(Name = "ChangePassword")]
        public async Task ChangePassword([Required] ChangePasswordInput input)
        {
            var user = _authorizationManager.User;

            var oldEncryptPassword = MD5Encryption.Encrypt(input.OldPassword.Trim());
            if (!user.UserPass.Equals(oldEncryptPassword)) throw Oops.Oh(ErrorCodes.u1004);

            // 禁止被修改 admin 密码
            if (user.UserName.Equals("admin")) throw Oops.Oh(ErrorCodes.u1005);

            user.UserPass = MD5Encryption.Encrypt(input.UserPass.Trim());
            user.UpdatedTime = DateTime.Now;
            await user.UpdateAsync();            
        }



        /// <summary>
        /// 用户列表 (select的option) 
        /// </summary>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.USER_List), HttpGet("/User/UserOptions"), ApiDescriptionSettings(Name = "UserOptions")]
        public async Task<List<UserItem>> UserOptionsAsync()
        {
            return await _memoryCache.GetOrCreateAsync($"user_items", async (_) =>
            {
                return await _userRepository.Where(a => a.IsDeleted == false && a.Enabled == true)
                .Select(u => new UserItem
                {
                    Id = u.Id,
                    UserName = u.UserName,
                    NickName = u.NickName
                })
                .ToListAsync();
            });



        }


        /// <summary>
        /// 修改当前用户信息（小程序）
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous, HttpPost("/User/WeiXinUserEdit"), ApiDescriptionSettings(Name = "WeiXinUserEdit")]
        public async Task WeiXinUserEditAsync(WeiXinUserEditInput input)
        {
            var val = await _userRepository.DetachedEntities.AnyAsync(a => a.Id == input.Id);
            if (val)
            {
                var editModle = input.Adapt<User>();
                await _userRepository.UpdateIncludeNowAsync(editModle, new[] {nameof(User.Mobile),nameof(User.NickName),nameof(User.ImageUrl),nameof(User.Remark) }, ignoreNullValues: true);
            }
            else
            {
                throw Oops.Oh("账号不存在，操作错误");
            }
        } 

        /// <summary>
        /// 更新用户头像和昵称
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [SecurityDefine(ConstPermission.USER_Edit), HttpPost("/User/UpdateWeiXinInfo"), ApiDescriptionSettings(Name = "UpdateWeiXinInfo")]
        public async Task UpdateWeiXinInfoAsync(WxUserPara input)
        {
            var userInfo = await _userRepository.FirstOrDefaultAsync(u => u.Id == input.UserId && u.IsDeleted == false);
            if (userInfo != null)
            {
                userInfo.NickName = input.NickName;                
                userInfo.ImageUrl = input.ImageUrl;
                await _userRepository.UpdateIncludeNowAsync(userInfo, new[] { nameof(User.NickName), nameof(User.ImageUrl) });
            }
            else
            {
                throw Oops.Oh("用户不存在");
            }
        }



    }
}
